#pragma once
#include "DataStructure/Common/Out.h"
#include "Utility/Algebra/Point.h"
#include "Utility/Algebra/Matrix.h"

#include "DataStructure/Input/Element/CHBDYGData.h"
#include "DataStructure/Input/Material/ThermalMaterial.h"
#include "SGFem/Integration/IntegrationFormula/Gauss2D2X2P.h"
#include "SGFem/Integration/ShapeFunction/Plane4NodeShpFunc.h"
#include "SGFem/ElementCalculator/Common/ElementCalculatorExport.h"
#include "SGFem/ElementCalculator/Interface/IElementCalculator.h"

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN
class ElementCalculator_DECLSPEC CHBDYGAREACalculator : public SG::FEMSolver::Element::IElementCalculator
{
public:
    CHBDYGAREACalculator () = default;
    virtual ~CHBDYGAREACalculator () = default;

    /// @brief 计算和节点坐标无关的变量
    virtual void Initialize (SG::DataStructure::FEM::ElementTypes type) override;
    
    /** @brief 获取边界单元上节点数量
     * 
     * @param [in] eleData 边界单元数据
     * @param [out] nNode   节点数量
    */ 
    void NumofNodes(const SG::DataStructure::Common::Id eleType, _OUT std::size_t& nNode) const;
    
    /** @brief 计算应变矩阵B
     * 
     * @param [in] iGauss 积分点索引
     * @param [in] coord 单元节点坐标
     * @param [out] B    应变矩阵
     * @param [out] j 积分点雅克比的行列式值
    */ 
    void ComputeStrainMatrix(std::size_t iGauss, const SG::Algebra::Matrix& coord, _OUT SG::Algebra::Matrix& B, _OUT SG::DataStructure::Common::Real& j) const;
    
    /** @brief 计算detJ
     * 
     * @param [in] iGauss 积分点索引
     * @param [in] coord 单元节点坐标
     * @param [out] j 积分点雅克比的行列式值
    */ 
    void ComputedetJ
    (
    std::size_t iGauss, 
    const SG::Algebra::Matrix& coord, 
    _OUT SG::DataStructure::Common::Real& j
    ) const;

    /** @brief 计算单元对流刚度矩阵
     * @param [in] coords 单元节点全局坐标
     * @param [in] material 材料特性
     * @param [out] ke2 单元对流刚度矩阵
    */
    void ComputeConvStiffness
    (
    const SG::Algebra::Matrix& coords,
    const SG::DataStructure::FEM::ThermalMaterial& material,
    _OUT SG::Algebra::Matrix& ke2
    );
    
    /** @brief 计算单元对流刚度矩阵
     * @param [in] coords 单元节点全局坐标
     * @param [in] h 单元节点对流换热系数
     * @param [out] ke2 单元对流刚度矩阵
    */
    void ComputeConvStiffness
    (
    const SG::Algebra::Matrix& coords,
    const std::vector<SG::DataStructure::Common::Real>& h,
    _OUT SG::Algebra::Matrix& ke2
    );

    /** @brief 计算单元辐射刚度矩阵
     * @param [in] coords 单元节点全局坐标
     * @param [in] Emissivity 发射率/黑度（0-1）
     * @param [in] T 辐射面1绝对温度
     * @param [in] Text 辐射面2绝对温度
     * @param [out] ke4 单元对流刚度矩阵
    */
    void ComputeRadStiffness
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::Common::Real& Emissivity,
    const std::vector<SG::DataStructure::Common::Real>& T,
    const SG::DataStructure::Common::Real& Text,
    _OUT SG::Algebra::Matrix& ke4
    );

    /** @brief 计算单元面对流荷载矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] material 材料特性
     * @param [in] Text 外部换热温度
     * @param [out] p3 单元面对流荷载矩阵
    */
    void ComputeConvLoad
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::FEM::ThermalMaterial& material,
    const SG::DataStructure::Common::Real& Text,
    _OUT SG::Algebra::Matrix& p3
    );
    
    /** @brief 计算单元面对流荷载矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] h 单元节点对流换热系数
     * @param [in] Text 外部换热温度
     * @param [out] p3 单元面对流荷载矩阵
    */
    void ComputeConvLoad
    (
    const SG::Algebra::Matrix& coords, 
    const std::vector<SG::DataStructure::Common::Real>& h,
    const SG::DataStructure::Common::Real& Text,
    _OUT SG::Algebra::Matrix& p3
    );

    /** @brief 计算单元面热流荷载矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] q 单元面热流量
     * @param [out] p2 单元面热流荷载矩阵
    */
    void ComputeHeatFluxLoad
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::Common::Real& q0,
    _OUT SG::Algebra::Matrix& p2
    );
    
    /** @brief 计算单元面热流荷载贡献，集成到荷载端中
     * @param [in] eleData 边界单元数据
     * @param [in] q0 单元面热流量
     * @param [out] sid 边界条件编号
    */
    void ComputeHeatFluxMatries 
    (
        const SG::DBManager::DBServiceFactorySP dbServiceFactory,
        const SG::DataStructure::FEM::CHBDYGData eleData,
        const SG::DataStructure::Common::Real& q0,
        const SG::DataStructure::Common::Id sid
    );
    
    /** @brief 计算单元面对流刚度与荷载贡献，集成到刚度与荷载端中
     * @param [out] sid 边界条件编号
    */
    void ComputeConvMatries 
    (
        const SG::DBManager::DBServiceFactorySP dbServiceFactory,
        const SG::DataStructure::Common::Id sid
    );

    virtual void ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) override;
    virtual void DataRecovery (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int subcaseId, SG::DataStructure::Common::Real time, const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) override;
    virtual void ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) override;
    static ElementCalculatorSP Create () {return std::make_shared<CHBDYGAREACalculator> ();}
    
private:
    SG::DataStructure::FEM::ElementTypes m_type;           ///< 单元类型
    SG::FEMSolver::Element::Gauss2D2X2P       m_integForm; ///< 积分格式
    SG::FEMSolver::Element::Plane4NodeShpFunc m_shpFunc; ///< 积分点上的形函数
    static std::size_t s_nNode4;                          ///< 四边形单元面节点数
    static std::size_t s_nNode3;                         ///< 三角形单元面节点数
    static std::size_t s_nDim;                           ///< 空间维度
};

SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE